﻿using AutoMapper;
using King.Box.Models.Db.Sys;
using King.Box.Models.Query.Sys;
using King.Box.Models.Util;
using King.Box.Models.View.Sys;
using King.Box.Utils.Global;
using King.Box.Utils.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace King.Box.Service.Impl
{
    public class SysService : ISysService
    {
        private readonly IDataService<Sys_User> _sysUserService;
        private readonly IDataService<Sys_Menu> _sysMenuService;
        private readonly IDataService<Sys_Permission> _sysPermissionService;
        public SysService(IDataService<Sys_Menu> sysMenuService, IDataService<Sys_Permission> sysPermissionService, IDataService<Sys_User> sysUserService)
        {
            _sysMenuService = sysMenuService;
            _sysUserService = sysUserService;
            _sysPermissionService = sysPermissionService;
        }

        #region 菜单
        /// <summary>
        /// 查询菜单
        /// </summary>
        /// <param name="queryParam"></param>
        /// <returns></returns>
        public PageResult<Sys_MenuData> SelectMenu(SysMenuQuery queryParam)
        {
            if (queryParam.limit == 0)
                queryParam.limit = 20;
            if (queryParam.offset == 0)
                queryParam.offset = 1;

            Expression<Func<Sys_Menu, bool>> condition = x => x.IsDelete == (int)GlobalEnum.YN.No;
            if (!string.IsNullOrEmpty(queryParam.name))
                condition = condition.And(x => x.Name.Contains(queryParam.name));
            if (queryParam.level > 0)
                condition = condition.And(x => x.Level == queryParam.level);
            if (queryParam.parentId > 0)
                condition = condition.And(x => x.ParentId == queryParam.parentId);

            int count;
            var sysMenus = _sysMenuService.Select(out count, condition, queryParam.offset, queryParam.limit, k => k.OrderBy(x => x.Level).ThenBy(x => x.Sort));
            var sysMenuData = this.PartInfo(sysMenus);

            return new PageResult<Sys_MenuData>()
            {
                total = count,
                rows = sysMenuData
            };
        }

        /// <summary>
        /// 查询菜单
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Sys_MenuData> SelectMenuLevel()
        {
            var menus = _sysMenuService.Select();
            return this.LevelInfo(menus);
        }

        /// <summary>
        /// 查询菜单
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Sys_MenuData> SelectMenu()
        {
            var menus = _sysMenuService.Select();
            return this.PartInfo(menus);
        }

        /// <summary>
        /// 菜单级别
        /// </summary>
        /// <param name="sysMenus"></param>
        /// <returns></returns>
        public IEnumerable<Sys_MenuData> LevelInfo(IEnumerable<Sys_Menu> sysMenus)
        {
            var menus = this.PartInfo(sysMenus);
            return this.LevelInfo(menus);
        }

        /// <summary>
        /// 菜单级别
        /// </summary>
        /// <param name="menus"></param>
        /// <returns></returns>
        private IEnumerable<Sys_MenuData> LevelInfo(IEnumerable<Sys_MenuData> menus)
        {
            var level1Menu = menus.Where(x => x.Level == (int)GlobalEnum.MenuLevel.Level1).OrderByDescending(x => x.Sort).ToList();
            level1Menu.ForEach(x =>
            {
                var level2Menu = menus.Where(z => z.ParentId == x.Id).OrderByDescending(z => z.Sort).ToList();
                level2Menu.ForEach(z =>
                {
                    var level3Menu = menus.Where(k => k.ParentId == z.Id).OrderByDescending(k => k.Sort).ToList();
                    z.SubMenus = level3Menu;
                });
                x.SubMenus = level2Menu;
            });
            return level1Menu;
        }

        /// <summary>
        /// 数据模型转换
        /// </summary>
        /// <param name="sysMenus"></param>
        /// <returns></returns>
        private IEnumerable<Sys_MenuData> PartInfo(IEnumerable<Sys_Menu> sysMenus)
        {
            var menus = Mapper.Map<IEnumerable<Sys_MenuData>>(sysMenus);
            this.PartInfo(menus);
            return menus;
        }

        /// <summary>
        /// 数据模型转换
        /// </summary>
        /// <param name="menus"></param>
        private void PartInfo(IEnumerable<Sys_MenuData> menus)
        {
            menus.ToList().ForEach(x =>
            {
                x.Parent = menus.FirstOrDefault(z => z.Id == x.ParentId);
                x.LevelName = GlobalEnum.GetEnumDescription<GlobalEnum.MenuLevel>(x.Level);
            });
        }
        #endregion

        #region 权限
        /// <summary>
        /// 查询权限
        /// </summary>
        /// <param name="queryParam"></param>
        /// <returns></returns>
        public PageResult<Sys_PermissionData> SelectPermission(SysPermissionQuery queryParam)
        {
            if (queryParam.limit == 0)
                queryParam.limit = 20;
            if (queryParam.offset == 0)
                queryParam.offset = 1;

            Expression<Func<Sys_Permission, bool>> condition = x => x.IsDelete == (int)GlobalEnum.YN.No;

            if (!string.IsNullOrEmpty(queryParam.description))
                condition = condition.And(x => x.Description.Contains(queryParam.description));
            if (queryParam.parentId > 0)
                condition = condition.And(x => x.ParentId == queryParam.parentId);
            if (queryParam.referType > 0)
                condition = condition.And(x => x.ReferType == queryParam.referType);

            int count;
            var sysPermissions = _sysPermissionService.Select(out count, condition, queryParam.offset, queryParam.limit, k => k.OrderBy(x => x.CreateTime));
            var sysPermissionData = this.PartInfo(sysPermissions);

            return new PageResult<Sys_PermissionData>()
            {
                total = count,
                rows = sysPermissionData
            };
        }

        /// <summary>
        /// 数据模型转换
        /// </summary>
        /// <param name="sysPermissions"></param>
        /// <returns></returns>
        public IEnumerable<Sys_PermissionData> PartInfo(IEnumerable<Sys_Permission> sysPermissions)
        {
            var permissions = Mapper.Map<IEnumerable<Sys_PermissionData>>(sysPermissions);
            this.PartInfo(permissions);
            return permissions;
        }

        /// <summary>
        /// 数据模型转换
        /// </summary>
        /// <param name="permissions"></param>
        public void PartInfo(IEnumerable<Sys_PermissionData> permissions)
        {
            permissions.ToList().ForEach(x =>
            {
                x.Parent = permissions.FirstOrDefault(z => z.Id == x.ParentId);
                x.ReferTypeName = GlobalEnum.GetEnumDescription<GlobalEnum.SysPermissionReferType>(x.ReferType);

                switch (x.ReferType)
                {
                    case (int)GlobalEnum.SysPermissionReferType.Menu:
                        x.Refer = _sysMenuService.Get(x.ReferId);
                        break;
                    case (int)GlobalEnum.SysPermissionReferType.Operation:
                        x.Refer = _sysPermissionService.Get(x.ReferId);
                        break;
                    default:
                        break;
                }
            });
        }
        #endregion

        #region 用户
        /// <summary>
        /// 数据模型转换
        /// </summary>
        /// <param name="sysUsers"></param>
        /// <returns></returns>
        private IEnumerable<Sys_UserData> PartInfo(IEnumerable<Sys_User> sysUsers)
        {
            return Mapper.Map<IEnumerable<Sys_UserData>>(sysUsers);
        }

        /// <summary>
        /// 查询用户
        /// </summary>
        /// <param name="queryParam"></param>
        /// <returns></returns>
        public PageResult<Sys_UserData> SelectUser(SysUserQuery queryParam)
        {
            if (queryParam.limit == 0)
                queryParam.limit = 20;
            if (queryParam.offset == 0)
                queryParam.offset = 1;

            Expression<Func<Sys_User, bool>> condition = x => x.IsDelete == (int)GlobalEnum.YN.No;
            if (!string.IsNullOrEmpty(queryParam.UserName))
                condition = condition.And(x => x.UserName.Contains(queryParam.UserName));

            int count;
            var sysUsers = _sysUserService.Select(out count, condition, queryParam.offset, queryParam.limit, k => k.OrderBy(x => x.Id));
            var sysUserData = this.PartInfo(sysUsers);

            return new PageResult<Sys_UserData>()
            {
                total = count,
                rows = sysUserData
            };
        }
        #endregion
    }
}
